package IC.Parser;

import java_cup.runtime.Symbol;
import java.lang.Math;


%%

%class Lexer
%public
%function next_token
%type Token
%line
%cup
%scanerror LexicalError
%state STRING
%{
StringBuffer str=new StringBuffer();
%}
%eofval{
	if (yystate() == STRING)
		throw new LexicalError("Lexical error: string is not closed ",yyline+1);
	return new Token(sym.EOF, yyline+1,"EOF");	
%eofval}


digit = [0-9]

ZERO = "0"
integer=  ([1-9]+{digit}*)|({ZERO}+)
illegalint=({ZERO}+)([1-9]+)



letter = [a-zA-Z]
 
class_identifier = [A-Z]({letter}|{digit})*

identifier=([a-z])({letter}|{digit}|"_")*

end_of_line = \r|\n|\r\n
space = {end_of_line} | [ \t\f]
illegalspace=[^\x20-\x7E]
comment   = ("/*" ~ "*/")|( "//" ([^\r\n])* {end_of_line})

%%




<YYINITIAL> {



"(" { return new Token(sym.LP,yyline+1,"("); }
")" { return new Token(sym.RP,yyline+1,")"); }
"=" { return new Token(sym.ASSIGN,yyline+1,"=");}
"boolean" { return new Token(sym.BOOLEAN,yyline+1,"boolean");}
"break" { return new Token(sym.BREAK,yyline+1,"break");}
"class" { return new Token(sym.CLASS,yyline+1,"class");}
"," { return new Token(sym.COMMA,yyline+1,",");}
"continue" { return new Token(sym.CONTINUE,yyline+1,"continue");}
"/" { return new Token(sym.DIVIDE,yyline+1,"/");}
"." { return new Token(sym.DOT,yyline+1,".");}
"==" { return new Token(sym.EQUAL,yyline+1,"==");}
"extends" { return new Token(sym.EXTENDS,yyline+1,"extends");}
"else" { return new Token(sym.ELSE,yyline+1,"else");}
"false" { return new Token(sym.FALSE,yyline+1,"false");}
">" { return new Token(sym.GT,yyline+1,">");}
">=" { return new Token(sym.GTE,yyline+1,">=");}
"if" { return new Token(sym.IF,yyline+1,"if");}
"int" { return new Token(sym.INT,yyline+1,"int");}
{illegalint} {throw new LexicalError ("Lexical error: illegal integer"+" '"+yytext() + "'", yyline+1);}
{integer} 
/*{


if ((Integer.parseInt(yytext()) > 2147483647) || (Integer.parseInt(yytext()) <= -2147483648))
{
throw new LexicalError("Lexical error: integer out of range "+ yytext(),yyline);
}

else return new Token(sym.INTEGER,yyline+1 ,Integer.parseInt(yytext()), "integer") 

;}
*/

{ try {
				return new Token(sym.INTEGER ,yyline+1 , Integer.parseInt(yytext()), "integer"); 
				}
			catch (NumberFormatException e) {
				throw new LexicalError("Lexical error: integer out of range " + yytext(),yyline); 
											}
		}
		
		;}
		
		
		
		
		
		
		


"[" { return new Token(sym.LB,yyline+1,"[");}
"{" { return new Token(sym.LCBR,yyline+1,"{");}
"length" { return new Token(sym.LENGTH,yyline+1,"length");}
"new" { return new Token(sym.NEW,yyline+1,"new");}
"!" { return new Token(sym.LNEG,yyline+1,"!");}
"&&" { return new Token(sym.LAND,yyline+1,"&&");}
"||" { return new Token(sym.LOR,yyline+1,"||");}
"<" { return new Token(sym.LT,yyline+1,"<");}
"<=" { return new Token(sym.LTE,yyline+1,"<=");}
"-" { return new Token(sym.MINUS,yyline+1,"-");}
"%" { return new Token(sym.MOD,yyline+1,"%");}
"*" { return new Token(sym.MULTIPLY,yyline+1,"*");}
"!=" { return new Token(sym.NEQUAL,yyline+1,"!=");}
"null" { return new Token(sym.NULL,yyline+1,"null");}
"+" { return new Token(sym.PLUS,yyline+1,"+");}
"]" { return new Token(sym.RB,yyline+1,"]");}
"}" { return new Token(sym.RCBR,yyline+1,"}");}
"return" { return new Token(sym.RETURN,yyline+1,"return");}
";" { return new Token(sym.SEMI,yyline+1,";");}
"static" { return new Token(sym.STATIC,yyline+1,"static");}
"string" { return new Token(sym.STRING,yyline+1,"string");}
"this" { return new Token(sym.THIS,yyline+1,"this");}
"true" { return new Token(sym.TRUE,yyline+1,"true");}
"void" { return new Token(sym.VOID,yyline+1,"void");}
"while" { return new Token(sym.WHILE,yyline+1,"while");}
\" {yybegin(STRING);str.setLength(0);str.append("");}
{space} {}
{comment} {}

{identifier} { return new Token(sym.ID,yyline+1,yytext(),"identifier");}
{class_identifier} { return new Token(sym.CLASS_ID,yyline+1,yytext(),"class_identifier");}

"/*" { throw new LexicalError("Lexical error: comment is not closed \"" + yytext() + "\"",yyline+1);}
. {throw new LexicalError("Lexical error: illegal character"+" '"+yytext()+"'", yyline+1);}
}


<STRING>{
\" {yybegin(YYINITIAL);str.append("");return new Token(sym.QUOTE, yyline+1, str.toString(),"string");}

 "\\t"  { str.append( "\t" ); }
 "\\n"  { str.append( "\n" ); }
 "\\\""  { str.append( "\\\"" ); }
 "\\\\"  { str.append( "\\\\" ); }
 {illegalspace} { throw new LexicalError("Lexical error: illegal space character", yyline+1);}
          
 "\\"    {throw new LexicalError("Lexical error: illegal character"+" '"+yytext()+"'", yyline+1);}
[^\"\\] {str.append(yytext()); }                    
}
